#ifndef _EVENT_INTERNAL_H_
#define _EVENT_INTERNAL_H_

#ifndef evtime_sec
#define evtime_sec 1000
#endif // !evtime_sec

#ifndef evtime_usec
#define evtime_usec 1000000
#endif // !evtime_usec

#ifndef ev_maxsec_mesec
#define ev_maxsec_mesec (((LONG_MAX)-999) / evtime_sec)
#endif // !ev_maxsec_mesec

#define ev_io_complete   1
#define ev_func_complete 2

#ifndef op_cmd_poll
#define op_cmd_poll 0x01
#endif // !op_cmd_poll

#ifndef op_cmd_exit
#define op_cmd_exit 0x02
#endif // !op_cmd_exit

typedef struct evloop_nodes_s evloop_nodes_t;
typedef struct evloop_clock_s evloop_clock_t;
typedef struct evbuf_s evbuf_t;
typedef _queue_t evloop_queue_t;
typedef _queue_t evoper_queue;
typedef unsigned int evoper_ls;
typedef struct evs_s evs_t;

#define op_ev_reading 0x01
#define op_ev_readed  0x02

#define op_ev_writeing 0x11
#define op_ev_writed   0x12

#define op_ev_timering    0x21
#define op_ev_timered     0x22
#define op_ev_timerfailed 0x23

#define op_ev_opening    0x31
#define op_ev_opened     0x32
#define op_ev_openfailed 0x33

#define op_ev_connecting    0x41
#define op_ev_connected     0x42
#define op_ev_connectfailed 0x43

#define op_ev_accepting    0x51
#define op_ev_accepted     0x52
#define op_ev_acceptfailed 0x53

#define op_ev_closeing 0x61
#define op_ev_closed   0x62

#ifndef ev_on
#define ev_on 0x00
#endif // !ev_on

#ifndef ev_off
#define ev_off 0x01
#endif // !ev_off

struct evs_s {
    _atomic_t v;
};

struct evbuf_s {
    buf_ptr ptr;
    buf_len len;
    buf_len off;
    buf_len byte;
    _mutex_t lock;
};

struct evoper_s {
    evtype t;
    void* ctx;
    void* private;

    evevent open;
    evevent conn;

    evevent read;
    evbuf_t rbuf;

    evevent write;
    evbuf_t wbuf;

    evevent accept;
    evoper_ls ls;

    evevent close;

    evevent oneshot;
    evevent eof;
    evevent post;
    evevent err;

    evevent vnode;       //  kqueue_vnode;
    evevent pending_eof; //  kqueue_vnode;

    union {
        _fd_t fd;
        _sock_t sock;
    };

    _heap_node_t node;
    ev_handler handler;
    evloop_t* loop;
    crt_msec msec;

    crterr code;
    evoper_queue queue;
};

typedef int (*ev_op)(int err, crterr code, evoper_t* oper, evoper_t* accepet_oper, evevent op);

struct evsysop_s {
    int (*op_alloc)(evloop_t* loop, int size);
    int (*op_dealloc)(evloop_t* loop);
    int (*op_handler)(evloop_t* loop, ev_op handler);
    int (*op_alloc_evoper)(evloop_t* loop, evoper_t* oper);
    int (*op_dealloc_evoper)(evloop_t* loop, evoper_t* oper);
    int (*op_enable_read)(evloop_t* loop, evoper_t* oper, short event, ev_time_t tv);
    int (*op_enable_write)(evloop_t* loop, evoper_t* oper, short event, ev_time_t tv);
    int (*op_disable_read)(evloop_t* loop, evoper_t* oper, short event);
    int (*op_disable_write)(evloop_t* loop, evoper_t* oper, short event);
    int (*op_cancel)(evloop_t* loop, evoper_t* oper);
    int (*op_open)(evloop_t* loop, evoper_t* oper, const evaddr_t* addr);
    int (*op_poll)(evloop_t* loop, evoper_t* oper);
    int (*op_add_connect)(evloop_t* loop, evoper_t* oper, const evaddr_t* addr, ev_time_t tv);
    int (*op_del_connect)(evloop_t* loop, evoper_t* oper);
    int (*op_dispatch)(evloop_t* loop, short event, crt_msec tm);
};

struct evloop_nodes_s {
    _mutex_t lock;
    _heap_t heap;
};

struct evloop_clock_s {
    _mutex_t lock;
    _clock_t clock;
    crt_msec msec;
};

struct evloop_s {
    evloop_status status;
    evsysop_t* sysop;
    void* evbase;
    void* ctx;
    void* mmctx;

    evloop_clock_t* clock;
    evloop_nodes_t* nodes;
    evloop_queue_t* queue;

    evmem_malloc mm_malloc;
    evmem_free mm_free;
    evloop_handler handler;
};

int evloop_nodes_addtime(evloop_nodes_t* nodes, evoper_t* oper);
int evloop_nodes_deltime(evloop_nodes_t* nodes, evoper_t* oper);
int evloop_nodes_gettime(evloop_nodes_t* nodes, evoper_t** oper);

int evloop_nodes_init(evloop_nodes_t* nodes);
int evloop_nodes_uninit(evloop_nodes_t* nodes);
int evloop_nodes_count(evloop_nodes_t* nodes, uint64_t* count);

int evloop_queue_init(evloop_queue_t* queue);
int evloop_queue_uninit(evloop_queue_t* queue);
int evloop_add_ev(evloop_queue_t* queue, evoper_queue* ev);
int evloop_del_ev(evloop_queue_t* queue, evoper_queue* ev);

int evloop_clock_init(evloop_clock_t* clock);
int evloop_clock_uninit(evloop_clock_t* clock);
int evloop_clock_update(evloop_clock_t* clock);
int evloop_clock_setmsec(evloop_clock_t* clock, crt_msec msec);
int evloop_clock_getmsec(evloop_clock_t* clock, crt_msec* msec);

int evloop_bind_evbase(evloop_t* loop, void* evbase);
void* evloop_evbase(evloop_t* loop);
void* evloop_sysop(evloop_t* loop);
void* evoper_evbase(evoper_t* oper);
void* evoper_private(evoper_t* oper);
int evoper_bind_private(evoper_t* oper, void* obj);

int evoper_op_init(evoper_t* oper);
int evoper_connect_op(evoper_t* oper, evevent op);
int evoper_connected(evoper_t* oper);
int evoper_accept_op(evoper_t* oper, evevent op);
int evoper_listen_size(evoper_t* oper, evoper_ls ls);
int evoper_read_op(evoper_t* oper, evevent op);
int evoper_reading(evoper_t* oper);
int evoper_write_op(evoper_t* oper, evevent op);
int evoper_writeing(evoper_t* oper);
int evoper_closeing(evoper_t* oper);
int evoper_close_op(evoper_t* oper, evevent op);

int evoper_post_op(evoper_t* oper, evevent op);
int evoper_eofing(evoper_t* oper);
int evoper_eof_op(evoper_t* oper, evevent op);
int evoper_erring(evoper_t* oper);
int evoper_err_op(evoper_t* oper, evevent op);

int evoper_assign_sock(evoper_t* oper, _sock_t sock);
int evoper_sock_connect(evoper_t* oper, const evaddr_t* addr);
int evoper_sock_connected(evoper_t* oper);

int complete_sock_accept(evloop_t* loop, int err, crterr code, evoper_t* oper, evoper_t* oper_t, ev_op func);
int complete_sock_connect(evloop_t* loop, int err, crterr code, evoper_t* oper, ev_op func);
int complete_sock_close(evloop_t* loop, int err, crterr code, evoper_t* oper, ev_op func);
int complete_sock_read(evloop_t* loop, int err, crterr code, evoper_t* oper, ev_op func);
int complete_sock_write(evloop_t* loop, int err, crterr code, evoper_t* oper, ev_op func);


int evbuf_init(evbuf_t* buf);
int evbuf_uninit(evbuf_t* buf);

int evbuf_is_eof(evbuf_t* buf);
int evbuf_bind(evbuf_t* buf, buf_ptr ptr, buf_len len, buf_len off);
int evbuf_get_buf(evbuf_t* buf, buf_ptr* ptr);
int evbuf_get_len(evbuf_t* buf, buf_len* len);
int evbuf_get_off(evbuf_t* buf, buf_len* off);

int evbuf_set_off(evbuf_t* buf, buf_len off);
int evbuf_op_off(evbuf_t* buf, buf_len off);
int is_evbuf_compelete(evbuf_t* buf);
int evoper_set_rbyte(evoper_t* oper, buf_len byte);
int evoper_set_wbyte(evoper_t* oper, buf_len byte);

int evs_init(evs_t* on);
int evs_uninit(evs_t* on);
int evs_on(evs_t* on);
int evs_off(evs_t* on);
int is_evs_on(evs_t* on);

#if (TARGET_OS != OS_WIN)

int evoper_tcpsock_send(evoper_t* oper, int err, crterr code, ev_op func);
int evoper_tcpsock_recv(evoper_t* oper, int err, crterr code, ev_op func);

#endif

#endif
